Imports System.Data

Public Class CustomBoundColumn
    Inherits DataGridBoundColumn

#Region "   Attributes"

    Private m_TemplateName As String

#End Region

#Region "   Properties"

    Public Property TemplateName() As String
        Get
            Return m_TemplateName
        End Get
        Set(value As String)
            m_TemplateName = value
        End Set
    End Property

    Private ReadOnly Property ModuleName As String
        Get
            Return "CustomBoundColumn"
        End Get
    End Property

#End Region

#Region "   ItemsSource DependencyProperty"

    Public Shared ReadOnly ItemsSourceProperty As DependencyProperty = DataGridComboBoxColumn.ItemsSourceProperty.AddOwner(GetType(CustomBoundColumn) _
                                                                                                                         , New PropertyMetadata(Nothing _
                                                                                                                                , New PropertyChangedCallback(AddressOf ItemsSourcePropertyChanged) _
                                                                                                                                , New CoerceValueCallback(AddressOf ItemSourceCoerceValueCallback)))

    Public Property ItemsSource As IEnumerable
        Get
            Return CType(GetValue(ItemsSourceProperty), IEnumerable)
        End Get
        Set(value As IEnumerable)
            SetValue(ItemsSourceProperty, value)
        End Set
    End Property

    Private Shared Sub ItemsSourcePropertyChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
    End Sub

    Private Shared Function ItemSourceCoerceValueCallback(d As DependencyObject, e As Object) As Object
        'TODO: somehow try and match itemsource to a combobodataitem, so use later. need to check if we then get cross threaded issues. maybe clone collection.
        If IsNothing(e) Then Return e
        If TypeOf e Is BindingListCollectionView Then
            Dim dv As DataView = DirectCast(e, BindingListCollectionView).SourceCollection
            Return dv.Table.AsEnumerable().ToList()
        Else
            Return DirectCast(e, ListCollectionView).SourceCollection
        End If
    End Function

#End Region

#Region "   GenerateElement"

    Protected Overrides Function GenerateElement(cell As DataGridCell, dataItem As Object) As FrameworkElement
        Try
            'get a pointer to the template we want to use to display the element
            Dim dgtc As DataGridTemplateColumn = cell.FindResource(TemplateName)
            'use the celltemplate for displaying
            Dim dc As FrameworkElement = dgtc.CellTemplate.LoadContent()
            dc.DataContext = dataItem.Properties(cell.Column.Header)
            Return dc
        Catch ex As Exception
            MessageBox.Show(String.Format("Error during {0}.{1}{2}", Reflection.MethodBase.GetCurrentMethod().Name, vbCrLf, ex.Message) _
                           , String.Format("{0} Error...", ModuleName) _
                           , MessageBoxButton.OK _
                           , MessageBoxImage.Error)
            Return Nothing
        End Try
    End Function

#End Region

#Region "   GenerateEditingElement"

    Protected Overrides Function GenerateEditingElement(cell As DataGridCell, dataItem As Object) As FrameworkElement
        Try
            'get a pointer to the template we want to use to display the element
            Dim dgtc As DataGridTemplateColumn = cell.FindResource(TemplateName)
            'use the celltemplate for displaying
            If IsNothing(dgtc.CellEditingTemplate) Then
                Return GenerateElement(cell, dataItem)
            End If
            Dim dc As FrameworkElement = dgtc.CellEditingTemplate.LoadContent()
            dc.DataContext = dataItem.Properties(cell.Column.Header)
            dc.DataContext.ItemsSource = ItemsSource
            Return dc
        Catch ex As Exception
            MessageBox.Show(String.Format("Error during {0}.{1}{2}", Reflection.MethodBase.GetCurrentMethod().Name, vbCrLf, ex.Message) _
                           , String.Format("{0} Error...", ModuleName) _
                           , MessageBoxButton.OK _
                           , MessageBoxImage.Error)
            Return Nothing
        End Try
    End Function

#End Region

End Class